package task

import (
	"encoding/csv"
	"encoding/xml"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"solargis/logging"
	"solargis/model/responseModel"
	"strconv"
	"strings"
	"time"
)

func Request(requestXML string, apiKey string, path string, days int, separator bool, separatorValue string) {
	var name = "currentDay"
	var logName = "请求当日数据"
	if days == 0 {
		name = "currentDay"
		logName = "当日请求"
	} else {
		name = "futureDay"
		logName = "请求1-" + strconv.Itoa(days) + "天数据"
	}
	if apiKey == "" {
		logging.Error.Printf("授权无效")
	}

	url := fmt.Sprintf("https://solargis.info/ws/rest/datadelivery/request?key=%s", apiKey)

	body, err := sendRequest(url, requestXML, logName)
	if err != nil {
		logging.Error.Printf("%v请求失败%v", logName, err)
	}
	logging.Info.Printf("%v请求成功", logName)

	// Write XML
	logging.Info.Printf("%v输出xml文件:开始创建目录", logName)
	xmlFilePth := path + string(filepath.Separator) + "xml" + string(filepath.Separator) + name + string(filepath.Separator)
	if err := os.MkdirAll(xmlFilePth, os.ModePerm); err != nil {
		logging.Error.Printf("%v输出xml文件:创建目录失败: %v", logName, err)
	}
	logging.Info.Printf("%v输出xml文件:创建目录成功", logName)

	xmlFilePth += time.Now().Format("200601021504") + ".xml"
	if err := os.WriteFile(xmlFilePth, body, 0644); err != nil {
		logging.Error.Printf("%v输出xml文件失败: %v", logName, err)
	}
	logging.Info.Printf("%v输出xml文件成功，位置: %v", logName, xmlFilePth)

	logging.Info.Printf("%v解析XML数据开始", logName)
	var response responseModel.DataDeliveryResponse
	if err := xml.Unmarshal(body, &response); err != nil {
		logging.Error.Printf("%v解析XML数据失败: %v", logName, err)
	}
	logging.Info.Printf("%v解析XML数据成功", logName)

	columns := strings.Fields(response.Sites.Columns)
	logging.Info.Printf("%v输出csv文件:开始创建目录", logName)
	csvFilePth := path + string(filepath.Separator) + "csv" + string(filepath.Separator) + name + string(filepath.Separator)
	if err := os.MkdirAll(csvFilePth, os.ModePerm); err != nil {
		logging.Error.Printf("%v输出csv文件:创建目录失败: %v", logName, err)
	}
	logging.Info.Printf("%v输出csv文件:创建目录成功", logName)
	csvFilePth += time.Now().Format("200601021504") + ".csv"
	if err := writeCSV(csvFilePth, columns, response.Sites.Rows, separator, separatorValue); err != nil {
		logging.Error.Printf("%v输出csv文件失败: %v", logName, err)

	}
	logging.Info.Printf("%v输出csv文件成功，位置: %v", logName, csvFilePth)
}

func sendRequest(url, requestXML string, logName string) ([]byte, error) {
	req, err := http.NewRequest("POST", url, strings.NewReader(requestXML))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/xml")

	client := &http.Client{Timeout: 30 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer func(Body io.ReadCloser) {
		err := Body.Close()
		if err != nil {

		}
	}(resp.Body)

	if resp.StatusCode == http.StatusBadRequest {
		logging.Error.Printf("%v错误请求：xml格式不正确：%v", logName, resp.StatusCode)
	} else if resp.StatusCode == http.StatusUnauthorized {
		logging.Error.Printf("%v未经授权：授权码无效：%v", logName, resp.StatusCode)
	} else if resp.StatusCode == http.StatusForbidden {
		logging.Error.Printf("%v订阅已限额：禁止请求%v", logName, resp.StatusCode)
	} else if resp.StatusCode == http.StatusNotFound {
		logging.Error.Printf("%v数据请求范围超出覆盖范围%v", logName, resp.StatusCode)
	} else if resp.StatusCode == http.StatusMethodNotAllowed {
		logging.Error.Printf("%v不允许 HTTP 方法%v", logName, resp.StatusCode)
	} else if resp.StatusCode == http.StatusTooManyRequests {
		logging.Error.Printf("%v超过调用速率或其他限制%v", logName, resp.StatusCode)
	} else if resp.StatusCode == http.StatusInternalServerError {
		logging.Error.Printf("%vSolagis内部服务器错误%v", logName, resp.StatusCode)
	}

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		logging.Error.Printf("%v读取返回值失败%v", logName, err)
		return nil, fmt.Errorf("读取返回值失败: %v", err)
	}

	return body, nil
}

func writeCSV(filename string, columns []string, rows []responseModel.Row, separator bool, separatorValue string) error {
	f, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer func(f *os.File) {
		err := f.Close()
		if err != nil {

		}
	}(f)

	writer := csv.NewWriter(f)
	defer writer.Flush()

	header := append([]string{"time"}, columns...)
	if len(header) > 0 {
		if separator {
			header[len(header)-1] = header[len(header)-1] + separatorValue
		}
	}
	if err := writer.Write(header); err != nil {
		return err
	}

	for _, row := range rows {
		values := strings.Fields(row.Values)
		record := append([]string{row.DateTime.Format("2006-01-02 15:04")}, values...)

		if len(record) > 0 {
			if separator {
				record[len(record)-1] = record[len(record)-1] + separatorValue
			}
		}
		if err := writer.Write(record); err != nil {
			return err
		}
	}

	return nil
}
